#include <fmt/format.h>
#include <kungfu/wingchun/msg.h>
#include <kungfu/yijinjing/util/util.h>
#include "mint/service/mbook.h"

namespace junyi
{
    namespace mint
    {
        namespace wrapper
        {
            MBook::MBook(const kungfu::yijinjing::data::location_ptr& location) : location_(location)
            {
            };

            void MBook::on_quote(kungfu::yijinjing::event_ptr event, const kungfu::wingchun::msg::data::Quote& quote)
            {
                SPDLOG_INFO("{} [{:08x}] received quote event msg_type: {}", location_->uname, location_->uid, event->msg_type());
            };

            void MBook::on_trade(kungfu::yijinjing::event_ptr event, const kungfu::wingchun::msg::data::Trade& trade)
            {
                SPDLOG_INFO("{} [{:08x}] received trade event msg_type: {}", location_->uname, location_->uid, event->msg_type());
            };

            void MBook::on_order(kungfu::yijinjing::event_ptr event, const kungfu::wingchun::msg::data::Order& order)
            {
                SPDLOG_INFO("{} [{:08x}] received order event msg_type: {}", location_->uname, location_->uid, event->msg_type());
            };

            void MBook::on_order_input(kungfu::yijinjing::event_ptr event, const kungfu::wingchun::msg::data::OrderInput& input)
            {
                SPDLOG_INFO("{} [{:08x}] received order_input event msg_type: {}", location_->uname, location_->uid, event->msg_type());
            };

            void MBook::on_positions(const std::vector<kungfu::wingchun::msg::data::Position>& positions)
            {
                for (auto& item : positions)
                {
                    uint32_t uid = get_position_uid(item.instrument_id, item.exchange_id, int(item.direction));
                    positions_[uid] = std::make_shared<Position>(item);
                }

                SPDLOG_INFO("call on_positions");
            };

            void MBook::on_position_details(const std::vector<kungfu::wingchun::msg::data::PositionDetail>& position_details)
            {
                SPDLOG_INFO("call on_position_details");
            };

            void MBook::on_asset(kungfu::yijinjing::event_ptr event, const kungfu::wingchun::msg::data::Asset& asset)
            {
                SPDLOG_INFO("{} [{:08x}] received trade event msg_type: {}", location_->uname, location_->uid, event->msg_type());
                SPDLOG_TRACE("data: {}", event->data_as_string());

                subject_.get_subscriber().on_next(event);
            };

            void MBook::on_trading_day(kungfu::yijinjing::event_ptr event, int64_t daytime)
            {
                SPDLOG_INFO("call on_trading_day");
            };

            ////////////////////////////////////////////////////////////////
            uint32_t MBook::get_position_uid(std::string instrument_id, std::string exchange_id, std::int32_t direction) 
            {
                const std::string position_uname = get_position_uname(instrument_id, exchange_id, direction);

                return kungfu::yijinjing::util::hash_str_32(position_uname);
            }

            std::string MBook::get_position_uname(std::string instrument_id, std::string exchange_id, std::int32_t direction)
            {
                return fmt::format("{}.{}.{}", instrument_id, exchange_id, direction);
            }

            void MBook::add_book_position(std::shared_ptr<Position> position_ptr)
            {
                uint32_t uid = get_position_uid(position_ptr->instrument_id, position_ptr->exchange_id, int(position_ptr->direction));

                positions_[uid] = position_ptr;
            }

            void MBook::add_book_subject(rxcpp::subjects::subject<kungfu::yijinjing::event_ptr>& subject)
            {
                subject_ = subject;
            }
        }
    }
}